﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace System.Windows.Art
{
    public sealed class ColorAccumulator : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private readonly ColorSpaceBase[] spaces;
        private readonly IColor[] colors;

        private Int32 masterIndex;
        private ColorSpaceBase masterSpace;
        //private ColorChannel masterChannel;

        //public ColorAccumulator(ColorChannel masterChannel)
        //{
        //    this.spaces = ColorSpaces.GetAll();
        //    this.colors = new IColor[this.spaces.Length];
            
        //    this.MasterChannel = masterChannel;
        //}

        public ColorAccumulator(IColor color)
        {
            this.spaces = ColorSpaces.GetAll();
            this.colors = new IColor[this.spaces.Length];

            this.Color = color;
        }

        //private void InvalidateMasterIndex()
        //{
        //    for (Int32 i = 0; i < this.spaces.Length; i++) if (this.spaces[i] == this.masterSpace) { this.masterIndex = i; break; }
        //}

        private void NotifyPropertyChanged(String propertyName)
        {
            if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public IColor GetColor(ColorSpaceBase space)
        {
            for (Int32 i = 0; i < this.spaces.Length; i++) if (space == this.spaces[i]) return (IColor)this.colors[i].Clone();
            return null;
        }

        public T GetColor<T>(ColorSpace<T> space) where T : IColor
        {
            for (Int32 i = 0; i < this.spaces.Length; i++) if (space == this.spaces[i]) return (T)this.colors[i].Clone();
            return default(T);
        }

        public Double GetValue(ColorChannel channel)
        {
            var space = channel.Owner;
            for (Int32 i = 0; i < this.spaces.Length; i++) if (space == this.spaces[i]) return this.colors[i].GetValue(channel);
            return 0.0;
        }

        public Double GetClassicValue(ColorChannel channel)
        {
            var space = channel.Owner;
            for (Int32 i = 0; i < this.spaces.Length; i++) if (space == this.spaces[i]) return this.colors[i].GetClassicValue(channel);
            return 0.0;
        }

        public void SetColor(IColor color)
        {
            var mediaColor = color.ToColor();
            var colorSpace = color.Space;

            for (Int32 i = 0; i < this.spaces.Length; i++)
            {
                var space = this.spaces[i];
                
                if (space == colorSpace) this.colors[i] = color;
                else this.colors[i] = space.FromColorBase(mediaColor);
            }

            this.NotifyPropertyChanged("Color");
        }

        public void SetValue(ColorChannel channel, Double value)
        {
            var colorSpace = channel.Owner;
            for (Int32 i = 0; i < this.spaces.Length; i++)
            {
                var space = this.spaces[i];
                if (space == colorSpace)
                {
                    var color = this.colors[i];
                    color.SetValue(channel, value);
                    this.SetColor(color);
                    return;
                }
            }
        }

        public void SetClassicValue(ColorChannel channel, Double value)
        {
            var colorSpace = channel.Owner;
            for (Int32 i = 0; i < this.spaces.Length; i++)
            {
                var space = this.spaces[i];
                if (space == colorSpace)
                {
                    var color = this.colors[i];
                    color.SetClassicValue(channel, value);
                    this.SetColor(color);
                    return;
                }
            }
        }

        //public ColorChannel MasterChannel
        //{
        //    get { return this.masterChannel; }
        //    set
        //    {
        //        if (value == null) throw new ArgumentNullException("value");
        //        else
        //        {
        //            this.masterChannel = value;
        //            this.masterSpace = value.Owner;
        //            this.InvalidateMasterIndex();
        //            this.NotifyPropertyChanged("MasterChannel");
        //        }
        //    }
        //}

        public ColorSpaceBase MasterSpace
        {
            get { return this.masterSpace; }
            set
            {
                this.masterSpace = value;
                for (Int32 i = 0; i < this.spaces.Length; i++) if (this.spaces[i] == value) { this.masterIndex = i; break; }
                this.NotifyPropertyChanged("MasterSpace");
            }
        }

        public IColor Color
        {
            get { return (IColor)this.colors[this.masterIndex].Clone(); }
            set
            {
                this.MasterSpace = value.Space;
                this.SetColor(value);
            }
        }
    }
}
